#
# Creates counting board markup
# NOTE: Counting Boards are matrices rotated 90 degrees clockwise
#
# 2009, Mike Widner <mikewidner@gmail.com>
#
########

package Fangcheng::LaTeX::CountingBoard;

use 5.006001;
use strict;
use warnings;
use vars qw( $AUTOLOAD @ISA );
use Fangcheng::Matrix;

require Fangcheng::LaTeX;

@ISA = qw( Fangcheng::LaTeX );

my $VERSION = '0.01';

sub execute {
	my ($self, $matrix) = @_;
	
	# we use 3 different matrices for holding differents parts of the output string 
	$self->width( Fangcheng::Matrix->new( $matrix->rows(), '' ) );		# handles the column widths		
	$self->grid( Fangcheng::Matrix->new( $matrix->rows(), '' ) );		# for boxes?
	$self->marks( Fangcheng::Matrix->new( $matrix->rows(), '' ) );		# handles marks for counting
	$self->board( Fangcheng::Matrix->new( $matrix->rows(), '' ) );		# holds completed counting board

	$self->makeBoxes( $matrix );
	$self->setColWidth( $matrix );
	$self->makeGrid( $matrix );
	
	return( $self );
}

sub wrapString {
	my ($self, $matrix, $str) = @_;
	my $head = '';
	$head .= qq|\\dpi{100}\\def\\zN{|;
	$head .= $matrix->rows();
	$head .= qq|}\\def\\zL{|;
	$head .= $matrix->rows() - 1;
	$head .= qq|}\\fbox{\\xymatrix \@H= 5mm {|;
	return( $head . $str . '}}' );
}

sub toString {
	my ($self) = @_;
	my $str = '';	
	foreach my $col ( 1 .. $self->board->columns ) {
		foreach my $row ( reverse( 1 .. $self->board->rows ) ) {
			$str .= $self->board->get( $row, $col );
		}
	}
	return( $self->wrapString( $self->board, $str ) );
}

# returns text for given stage
sub description {
	my ($self) = @_;
	return( 'We arrange the entries on the counting board as follows (note that we remove any fractions by multiplying the entire column by a suitable integer):' );
}

sub setColWidth {
	my ($self, $matrix) = @_;
	my ($maxwidth, $width);
	foreach my $row ( 1 .. $matrix->rows() ) {
		$maxwidth = 0;
		foreach my $col ( 1 .. $matrix->columns() ) {
			my $val = $matrix->get( $row, $col );
			$width = length( $val );
			if ( $width > $maxwidth ) {
				$maxwidth = $width;
			}
		}
		my $size = 7 * $maxwidth;
		$size .= "mm";
		foreach my $col ( 1 .. $matrix->columns() ) {
			$self->width->set( $row, $col, $maxwidth );
		}
	}
}

# since it seems that the value is ALWAYS 'm' we could probably just
# factor this out and put a hard-coded string into getGridValues
# but just in case there are cases I haven't accounted for (based on original code)
# I'm leaving this here for now
sub makeBoxes {
	my ($self, $matrix) = @_;
	foreach my $row ( reverse( 1 .. $matrix->rows() ) ) {
		foreach my $col ( 1 .. $matrix->columns() ) {
			$self->grid->set( $row, $col, 'm' );
		}
	}
}

sub addGrid {
	my ($self, $matrix) = @_;
	foreach my $row ( reverse( 2 .. $matrix->rows() ) ) {
		my $val = $self->marks->get( $row, 1 );
		if ( $val !~ /zud$/ ) {
			$val .= '\\zud';
		}
		$self->marks->set( $row, 1, $val );
	}	
	foreach my $col ( 2 .. $matrix->columns() ) {
		my $val = $self->marks->get( 1, $col );
		if ( $val !~ /zlr$/ ) {
			$val .= '\\zlr';
		}
		$self->marks->set( 1, $col, $val );
	}
}

sub getGridValues {
	my ($self, $matrix, $row, $col) = @_;
	my $val = $matrix->get( $row, $col );
	my $width = $self->width->get( $row, $col );
	my $grid = $self->grid->get( $row, $col );
	my $mark = $self->marks->get( $row, $col );
	return( $val, $width, $grid, $mark );
}

sub getGridString {
	my ($self, $val, $width, $grid, $mark) = @_;
	return( qq|\\zq{$val}{$width}{$grid}{$mark}| );
}

# this function rotates the matrix 90 degrees clockwise
# and turns it into a counting board
sub makeGrid {
	my ($self, $matrix) = @_;
	$self->addGrid( $matrix );
	my ($str, $col, $row);

	foreach $col ( 1 .. $matrix->columns() ) {
		foreach $row ( reverse( 1 .. $matrix->rows() ) ) {
			$str = $self->getGridString( $self->getGridValues( $matrix, $row, $col ) ) . ' &';
			$self->board->set( $row, $col, $str );
		}
		$str =~ s/\s&$/\\\\/;	# replace trailing ampersand from final loop with end of line marker
		$self->board->set( 1, $col, $str );
	}
}


1;